package com.shelpe.service.simbaproxy.mock;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.MultiValueMap;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.shelpe.service.simbaproxy.mock.MockProperties.MockMethod;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MockFilter extends ZuulFilter {

	private MockProperties mockProperties;
	
	private ProxyRequestHelper proxyRequestHelper = new ProxyRequestHelper();
	@Autowired
	private ObjectMapper objectMapper;

	@Override
	public boolean shouldFilter(){
		RequestContext ctx = RequestContext.getCurrentContext();
		return (ctx.getRouteHost() != null && !ctx.containsKey("error.status_code"));
	}

	@Override
	public Object run() {
		RequestContext cxt = RequestContext.getCurrentContext();
		
		String uri = cxt.getRequest().getRequestURI();
		String[] methods = uri.split("/");
		String method = methods[methods.length - 1];
		String nick = this.pickup(cxt, "nick");

		String fileName = nick != null ? ("nick_" + nick) : "default";
		String key = this.pickupKey(method);
		if (key != null) {
			String value = this.pickup(cxt, key);
			if (value != null) {
				fileName = key + "_" + value;
			}
		}

		fileName = (this.mockProperties.getRoot() != null ? this.mockProperties.getRoot() : "/data") + "/" + method + "/" + fileName
				+ ".json";

		log.debug("fetch data from json file: {}", fileName);
		Resource resource = new FileSystemResource(fileName);
		try {
			log.debug("resource desc: {}", resource.getDescription());
			InputStream in = resource.getInputStream();
			
			JsonNode node = this.objectMapper.reader().readTree(in);
			log.debug("json node: {}", node.toString());
			
	        String json = this.objectMapper.writer().writeValueAsString(node);
	        log.debug("json: {}", json);
	        
	        HttpServletRequest request = cxt.getRequest();
			MultiValueMap<String, String> headers = this.proxyRequestHelper.buildZuulRequestHeaders(request);
			proxyRequestHelper.setResponse(200, null, headers);
			cxt.setResponseBody(json);
		} catch (IOException e) {
			log.error("IOException", e);
			cxt.setResponseStatusCode(404);
		}

		cxt.set("simbaproxy.mocked", true);
		cxt.setSendZuulResponse(false);
		return null;
	}

	@Override
	public String filterType() {
		return "route";
	}

	@Override
	public int filterOrder() {
		return 99;
	}

	public void setMockProperties(MockProperties mockProperties) {
		this.mockProperties = mockProperties;
	}


	public String pickup(RequestContext cxt, String key) {
		return cxt.getRequest().getParameter(key);
	}

	public String pickupKey(String method) {
		String key = null;
		for(Entry<String, MockMethod> en:this.mockProperties.getMethods().entrySet()){
			if(method.equals(en.getValue().getName())){
				key = en.getValue().getKey();
				break;
			}
		}

		return key;
	}

}
